package basics;

import java.io.IOException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Dieses Klasse startet die RMI_Registry.
 * */
public class RMIRegStarter
{
	private static RMIRegStarter singleton = null;
	private final String rmi = "rmiregistry";
	private final String client = "BattleShipClient.jar";
	private final String common = "BattleShipCommon.jar";
	private final String server = "BattleShipServer.jar";
	private final String codeBaseComand = "-J-Djava.rmi.server.codebase=";
	private String rmiPath;
	private String clientPath;
	private String commonPath;
	private String serverPath;
	private String basePath; 
	private String filePath;
	private RMIThread rmiThread;
	private Thread thread;
	
	/**@return Einen Instanz von RMIRegStarter*/
	public static RMIRegStarter GetInstance()
	{
		if(singleton == null)
			singleton = new RMIRegStarter();
		return singleton;
	}
	
	private RMIRegStarter()
	{
		basePath = getBasePath(RMIRegStarter.class);
		if(basePath.contains("basics"))
			basePath = getBasePath(RMIRegStarter.class).substring(0, basePath.indexOf("basics"));

		basePath = basePath + "Lib/";
		
		filePath = getClassPath(RMIRegStarter.class);
		if(filePath.contains("basics"))
			filePath = filePath.substring(0, filePath.indexOf("basics"));
		if(filePath.startsWith("jar:"))
			filePath = filePath.replaceFirst("jar:", "");
		if(filePath.contains("BattleShip.jar"))
			filePath = filePath.replaceAll("BattleShip.jar!", "");
		if(filePath.endsWith("\\\\"))
			filePath = filePath.replace("\\\\", "\\");
		filePath = filePath + "Lib/";
		rmiPath = "\"" + basePath + rmi + "\"";
		clientPath = filePath + client;
		commonPath = filePath + common;
		serverPath = filePath + server;
		rmiThread = new RMIThread();
		thread = new Thread(rmiThread);
	} 
	
	/**Diese Methode startet die RMIRegistry*/
	public void startNewRMIThread()
	{
		thread.start();
   	}
	
	/**Diese Methode stoppt die RMIRegistry*/
	public void stopRMIThread()
	{
	   rmiThread.StopReg();
   	}
	   
	private class RMIThread implements Runnable
	{
	   private Process pro;
	   private boolean started = false;
	   private boolean run = true;
	 
	   /**
	    * Beendet und bereinigt den laufenden Prozess 
	    *@Override
	   **/
		public void finalize()
		{
			try
			{
				super.finalize();
			} catch (Throwable e)
			{
				e.printStackTrace();
			}
			finally
			{
				pro.destroy();
			}
		}
	   
	   protected void StopReg()
	   {
		   run = false;
	   }
	   
	   /*
	    * Startet den Prozess der RMIRegistry 
	    *@Override
	   ***/
	   public void run()
	   {
		   String command = rmiPath
		   	+ " " + codeBaseComand
		   	+ "\""
		   	+ commonPath
			+ " " + clientPath
			+ " " + serverPath
			+ "\"";
		   System.out.println(command);
		   command = command.replaceAll("/", "\\\\");
		   command = command.replaceAll("%20", " ");
		   System.out.println(command);
		   if(!started)
		   {
			   try 
			   {
					pro = Runtime.getRuntime().exec(command);
					started = true;
			   } catch (IOException e) 
			   {
					System.err.println(e);
					System.exit(0);
			   }
		   }
		   while(run)
		   {
			   try
			   {
				   Thread.sleep(5000);
			   } catch (InterruptedException e)
			   {
				   e.printStackTrace();
			   }
		   }
		   pro.destroy();
		   pro = null;
	   }
	}

	@SuppressWarnings("unchecked")
	private String getBasePath(Class clazz)
	{
	   String raw=getClassPath(clazz);
	   if(raw == null) 
	   {
		   return ".";
	   }
	   String found = null;
	   Pattern p = 
	   Pattern.compile(".*?file:(\\/{1,2})(.+?)[^\\\\\\/]+\\.(jar|class).*");
	   Matcher m = p.matcher(raw);
	   if(m.matches())
	   {
		   found = m.group(2);
		   if(found.matches("[a-zA-Z]:.+"))
		   {
			   return found;
		   }
		   return m.group(1)+found;
	   }

	   return found;
	}
	   
   @SuppressWarnings("unchecked")
   private String getClassPath( Class clazz )
   { 
	   ClassLoader loader = clazz.getClassLoader();
    
	   if ( loader == null ) 
	   {
          return null;
	   }
	   URL url = loader.getResource(clazz.getName().replace('.','/')
                                     + ".class");
	   return ( url != null ) ? url.toString() : null;
  }

}
